這篇文章我們將帶領大家直接實作如何將程式分別燒錄到 ESP32 與 ATmega328P,並學習如何讓兩顆微控制器相互通訊。除了基礎教學之外,也會教大家使用正面的 LCD 來顯示接收到的資訊。
教學原文參考:ESP32 與 ATmega328P 的 UART 通訊
在 Pixel:Bit 上面有一些元件和模組,需要額外安裝程式庫才能正常使用它們。請點選「https://github.com/CIRCUSPi/tca5405」、「https://github.com/CIRCUSPi/TFT_eSPI」網址下載兩個必須的程式庫。
下載方式相當簡單,進到頁面後可以看到「Code」按鈕,點選後選擇「Download ZIP」就能將檔案整個下載下來。
這些程式庫無法與相似的程式庫相容,請確實下載這兩個程式庫。
接著回到Arduino IDE,點選「草稿碼」>「匯入程式庫」>「加入.ZIP程式庫…」。
請找到剛剛下載的程式庫並按下「開啟」。
成功的話,就會在訊息欄上方看到「已加入程式庫,請檢查…」
請依照上方「加入.ZIP程式庫…」步驟再新增「另一個程式庫」。
為了方便大家學習,我們先下載這個單元會用到的範例程式。與剛剛下載程式庫一樣,看到「Code」按鈕,點選後選擇「Download ZIP」就能將檔案整個下載下來。
解壓縮後,這個單元的所有範例程式,都放在資料夾名稱為「06.Uart Communication」。
學會顯示訊息是相當重要的功能,可以讓我們不外加其他裝置的情況下,經由螢幕將訊息顯示出來,可用來確認程式是否正確,是個除錯的好工具。
讓我們來看一下顯示訊息是怎麼運作的,請開啟「06.Uart Communication」資料夾,打開範例程式名稱為「01.LCD_Show_ESP32」,進到資料夾對裡面的程式檔案點兩下即可開啟。
完整程式碼如下所示:
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
void setup() {
// Initialise the TFT
tft.init();
tft.setRotation(3);
tft.fillScreen(TFT_BLACK);
// Show text
tft.setCursor(0, 0, 2); //(1, 2, 4, 6, 7, 8)
tft.setTextColor(TFT_ORANGE, TFT_BLACK);
tft.setTextSize(2); // 1~7
tft.println("Hello pixel:bit.");
}
void loop() {
}
在使用 LCD 螢幕之前需要匯入相關程式庫,並賦予物件功能,被賦予的物件名稱為「tft」,之後調用顯示功能可直接以 tft 代稱。
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
接著在 setup 區塊,我們初始化顯示螢幕,並旋轉螢幕方向以符合 Pixel:Bit 的配置,最後將螢幕顯示黑色(有點類似清空所有訊息的感覺)。
// Initialise the TFT
tft.init();
tft.setRotation(3);
tft.fillScreen(TFT_BLACK);
預設的顏色總共有 24 種,如下表所示:
顯示文字有幾個步驟,第一是決定位置與字型,螢幕像素大小為 240 x 240,您可以在這個範圍內決定從哪個位置開始顯示文字,程式「setCursor(0, 0, 2)」括弧內的頭兩個數字表示 x, y 座標,最後一個則是字型,共有 6 種字型(1, 2, 4, 6, 7, 8),以填入數字的方式選擇字型,每個字型支援的最大尺寸也不同。
第二步驟是決定文字顏色與背景顏色,程式「setTextColor(TFT_ORANGE, TFT_BLACK)」括弧內的第一個顏色是指文字顏色,另一個是背景顏色。
// Show text
tft.setCursor(0, 0, 2); //(1, 2, 4, 6, 7, 8)
tft.setTextColor(TFT_ORANGE, TFT_BLACK);
tft.setTextSize(2); // 1~7
tft.println("Hello pixel:bit.");
接著是文字大小,共有 7 種尺寸,填入數字越大,文字尺寸越大。最後則是使用程式「println(“填入要顯示的文字”)」顯示一行文字。
上圖程式是顯示一行字型為 2 大小為 2,顏色為橘色的文字,文字內容是「Hello pixel:bit.」。
知道程式所要完成的功能後,我們將程式上傳到 Pixel:Bit,看一下螢幕顯示的效果。因為負責處理螢幕顯示的是 ESP32,所以首先將 Pixel:Bit 上面的 UART 切換開關,切至「ESP」模式。
接下來連接 Micro USB 數據線至 Pixel:Bit 與電腦,並於「工具」>「開發板」的欄位選擇「AI Thinker ESP32-CAM」這塊開發板,並選擇正確的「序列埠」,序列埠的編號會依照您自己的電腦設定而與下圖有所不同。
設定完成後,請按下燒錄按鈕將程式燒錄到 Pixel:Bit。燒錄過程會需要一段時間,完成後會在訊息欄內收到提示。
燒錄完成,即可在 Pixel:Bit 上看到剛剛撰寫的文字。
接下來讓我們學習如何在 ESP32 與 ATmega328P 裡,撰寫能相互通訊的程式。
這個功能非常方便,例如我們可以讓 ATmega328P 連接感測器,並讀取環境資料,ESP32 負責顯示資訊與上傳資料到雲端。或是 ESP32 將效能全力用在影像辨識,而控制夾爪的工作就交給 ATmega328P,解決了單一控制器會遇到的多工問題。
我們以 ATmega328P 為發送訊息者,ESP32 為接收者,並負責將收到的訊息顯示在螢幕上。先來看 ESP32 這邊的程式碼,請開啟「02.UART_Read_and_Show_ESP32」。
完整程式碼如下所示:
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
String inputString = "";
void setup() {
// initialize serial:
Serial.begin(57600);
// Initialise the TFT
tft.init();
tft.setRotation(3);
tft.fillScreen(TFT_BLACK);
}
void loop() {
if (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
if (inChar == '\n') {
tft.fillScreen(TFT_BLACK);
tft.setCursor(0, 0, 2);
tft.setTextColor(TFT_ORANGE, TFT_BLACK); tft.setTextSize(7);
tft.println(inputString);
inputString = "";
}
}
}
與上個程式一樣匯入程式庫並賦予物件,在這裡新增一個字串類型的變數「inputString」並賦予值為"",這個變數會用來儲存從 ATmega328P 接收到的訊息。
#include <TFT_eSPI.h>
TFT_eSPI tft = TFT_eSPI();
String inputString = "";
在 setup 的區塊,我們啟用 UART 功能 Serial,並賦予傳輸速率為「57600」,接著初始化顯示螢幕並顯示黑色。
// initialize serial:
Serial.begin(57600);
// Initialise the TFT
tft.init();
tft.setRotation(3);
tft.fillScreen(TFT_BLACK);
在 loop 的區塊,我們透過「Serial.available()」這個程式檢查 Serial 連線時,是否有訊息傳送過來。並新增一個字元類型的變數「inChar」來接收訊息,再使用變數「inputString」將一個個訊息組合起來。
每次接收一個訊息後都會檢查變數「inChar」,查看接收到的訊息是否等於換行訊息「’\n’」。若是收到換行訊息,表示資料傳輸完成,我們就能透過上個程式學到的顯示文字,將收到的訊息顯示到螢幕上。
if (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
if (inChar == '\n') {
tft.fillScreen(TFT_BLACK);
tft.setCursor(0, 0, 2);
tft.setTextColor(TFT_ORANGE, TFT_BLACK); tft.setTextSize(7);
tft.println(inputString);
inputString = "";
}
}
ESP32 接收與顯示的程式就如上圖所示,現在將這個程式燒錄到 ESP32 裡。
請接續「ESP32 與 ATmega328P 的 UART 通訊(Part 2)」。